//
//  HttpManager.m
//  MetenEnglish
//
//  Created by Hsn on 14/11/19.
//  Copyright (c) 2014年 Shenzhen Securities Information Co., Ltd. All rights reserved.
//

#import "HttpManager.h"
#import "ASIFormDataRequest.h"
#import "NetWork.h"
#import "OCGumbo+Query.h"
#import "HTMLParser.h"
#import "ASINetworkQueue.h"

static HttpManager *httpManager = nil;

typedef NS_ENUM(NSInteger, REQUEST_TYPE){
    REQUEST_LOGIN = 0,
    REQUEST_SEARCHCOURSE,
    REQUEST_COURSES_LIST,
    REQUEST_RESERVECOURSE,
    REQUEST_USERLEVEL,
    REQUEST_CANCEL,
    REQUEST_STANDBY,
    REQUEST_CANCEL_QUEUE
};

@interface HttpManager () {
    NSArray *_cookies;
    ASINetworkQueue *_queue;
    
    NSString *_userName;
    NSString *_password;
    NSString *_checkCode;
    
}

@end

@implementation HttpManager

+ (HttpManager *)share {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        httpManager = [[HttpManager alloc] init];
    });
    return httpManager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _queue = [ASINetworkQueue queue];
        [_queue setDelegate:self];
        [_queue setMaxConcurrentOperationCount:5];
        [_queue go];
        
        _reservedCourses = [[NSMutableArray alloc] init];
        _isFresh = NO;
    }
    return self;
}

- (void)loginMetenWithUserName:(NSString *)userName
                      password:(NSString *)password {
    _userName = userName;
    _password = password;
    [self getCheckCode];
}


- (void)loginMetenWithUserName:(NSString *)userName
                      password:(NSString *)password
                     checkCode:(NSString *)checkCode {
    NSURL *loginURL = [NSURL URLWithString:LOGIN_URL];
    ASIFormDataRequest *loginRequest = [ASIFormDataRequest requestWithURL:loginURL];
    loginRequest.userInfo = @{USERNAME_KEY:userName,
                              PASSWORD_KEY:password};
    loginRequest.tag = REQUEST_LOGIN;
    [loginRequest setPostValue:userName forKey:@"UserName"];
    [loginRequest setPostValue:password forKey:@"Password"];
    [loginRequest setPostValue:checkCode forKey:@"CheckCode"];
    loginRequest.delegate = self;
    [loginRequest startAsynchronous];
}

- (void)getCheckCode {
    NSURL *url = [NSURL URLWithString:CHECKCODE_URL];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if ([data length] > 0 && connectionError == nil) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSDictionary *dic = [httpResponse allHeaderFields];
            NSString *setCookie = [dic objectForKey:@"Set-Cookie"];
            _checkCode = [setCookie substringWithRange:NSMakeRange(22, 4)];
            
            [self loginMetenWithUserName:_userName
                                password:_password
                               checkCode:_checkCode];
            
        }
        else {
//            [SVProgressHUD dismissWithError:@"login failure!"];
        }
    }];
}

- (void)searchCourses:(NSInteger)pageIndex {
    NSString *urlString = [NSString stringWithFormat:@"http://www.365eme.com/BookRecord/SearchBookRecordList?pageIndex=%ld", (long)pageIndex];
    ASIFormDataRequest *searchRequest = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
    searchRequest.tag = REQUEST_SEARCHCOURSE;

    searchRequest.userInfo = @{@"page":[NSNumber numberWithInteger:pageIndex]};
    
    [searchRequest setDelegate:self];
    [searchRequest setRequestCookies:[NSMutableArray arrayWithArray:_cookies]];
    [searchRequest setPostValue:@"" forKey:@"IsStudentRated"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd"];
    NSString *beginDate = [formatter stringFromDate:[NSDate date]];
    [searchRequest setPostValue:beginDate forKey:@"BeginDate"];
    [searchRequest setPostValue:@"" forKey:@"EndDate"];
    [searchRequest setPostValue:@"true" forKey:@"IsWaiting"];
    [searchRequest setPostValue:@"false" forKey:@"IsHasPass"];
    [searchRequest setPostValue:@"false" forKey:@"IsNotRate"];
    [searchRequest setPostValue:@"false" forKey:@"IsUnBook"];
    [searchRequest setPostValue:@"XMLHttpRequest" forKey:@"X-Requested-With"];
    
    [searchRequest startAsynchronous];
}

- (void)courseList:(NSUInteger)branchId productLevelId:(NSUInteger)productLevelId {
    NSURL *url = [NSURL URLWithString:COURSER_LIST];
    ASIFormDataRequest *couserListRequest = [[ASIFormDataRequest alloc] initWithURL:url];
    couserListRequest.tag = REQUEST_COURSES_LIST;
    
    [couserListRequest setDelegate:self];
    [couserListRequest setPostValue:[NSNumber numberWithInteger:branchId] forKey:@"branchId"];
    [couserListRequest setPostValue:[NSNumber numberWithInteger:productLevelId] forKey:@"productLevelId"];
    
    [couserListRequest startAsynchronous];
}

- (void)reserveCourse:(NSString *)courseID requestUserInfo:(CourseModel *)model {
    NSURL *url = [NSURL URLWithString:RESERVE_URL];
    ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
    //发起请求时保存 CourseModel 方便用于刷新界面
    request.userInfo = @{@"course":model};
    request.tag = REQUEST_RESERVECOURSE;
    request.delegate = self;
    
    NSString *productLevelId = [[NSUserDefaults standardUserDefaults] objectForKey:LEVEL_KEY];
    [request setPostValue:productLevelId forKey:@"productLevelId"];
    [request setPostValue:courseID forKey:@"arrangeCourseId"];
    
    [_queue addOperation:request];
    
}

- (void)standByCourse:(CourseModel *)model{
    NSURL *url = [NSURL URLWithString:STANDBY_URL];
    ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
    request.userInfo = @{@"course":model};
    request.tag = REQUEST_STANDBY;
    request.delegate = self;
    
    NSString *productLevelId = [[NSUserDefaults standardUserDefaults] objectForKey:LEVEL_KEY];
    NSString *arrgangeCourseId = [model getCourseId];
    [request setPostValue:productLevelId forKey:@"productLevelId"];
    [request setPostValue:arrgangeCourseId forKey:@"arrangeCourseId"];
    
    [request startAsynchronous];
}

- (void)cancelStandByCourse:(CourseModel *)model {
    NSURL *url = [NSURL URLWithString:CANCEL_STANDBY_URL];
    ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
    request.userInfo = @{@"course":model};
    request.tag = REQUEST_CANCEL_QUEUE;
    request.delegate = self;
    
    NSString *arrangeCourseId = [model getCourseId];
    [request setPostValue:arrangeCourseId forKey:@"arrangeCourseId"];
    
    [request startAsynchronous];
}

- (void)cancelReservedCourse:(NSString *)courseId {
    NSURL *url = [NSURL URLWithString:CANCEL_RESERVED_URL];
    ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
    [request setPostValue:CANCEL_REASON forKey:@"UnBookRecordReason"];
    [request setPostValue:[NSNumber numberWithInteger:[courseId integerValue]] forKey:@"UnBookRecordId"];
    [request setPostValue:@"XMLHttpRequest" forKey:@"X-Requested-With"];
    request.delegate = self;
    request.tag = REQUEST_CANCEL;
    
    [request startAsynchronous];
}

/**
 * @ get UserLevel
 */

- (void)userLevel:(NSString *)studentId {
    NSURL *url = [NSURL URLWithString:USER_LEVEL_URL];
    ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
    [request setPostValue:studentId forKey:@"studentId"];
    request.delegate = self;
    request.tag = REQUEST_USERLEVEL;
    [request startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request {
    switch (request.tag) {
        case REQUEST_LOGIN:
            [self loginSuccess:request];
            break;
        case REQUEST_SEARCHCOURSE:
            [self searchSuccess:request];
            break;
        case REQUEST_COURSES_LIST:
            [self courseListSuccess:request];
            break;
        case REQUEST_RESERVECOURSE:
            [self reserveCourseSuccess:request];
            break;
        case REQUEST_USERLEVEL:
            [self parseUserLevel:request];
            break;
        case REQUEST_CANCEL:
            [self cancelHandle:request];
            break;
        case REQUEST_STANDBY:
        case REQUEST_CANCEL_QUEUE:
            [self standByOrCancelQueueBack:request];
            break;
        default:
            break;
    }
}

#pragma mark - Process request Data

/**
 *  登录成功
 *
 *  @param request
 */
- (void)loginSuccess:(ASIHTTPRequest *)request {

    NSString *userName = [request.userInfo objectForKey:USERNAME_KEY];
    NSString *password = [request.userInfo objectForKey:PASSWORD_KEY];
    
    [[NSUserDefaults standardUserDefaults] setValue:userName forKey:USERNAME_KEY];
    [[NSUserDefaults standardUserDefaults] setValue:password forKey:PASSWORD_KEY];
    [[NSUserDefaults standardUserDefaults] synchronize];
    BOOL isPersistLogin = [[[NSUserDefaults standardUserDefaults] objectForKey:PERSISTLOGIN_KEY] boolValue];
    //非持续登录,获取学生ID,学生级别
    if (!isPersistLogin) {
        [self getStudentId:request];
    }
    _cookies = [request requestCookies];
    if (_loginDelegate && [_loginDelegate respondsToSelector:@selector(loginSuccess)]) {
        [_loginDelegate performSelector:@selector(loginSuccess)];
    }
}

- (void)searchSuccess:(ASIHTTPRequest *)request {
    // clear the old data
    
    if (_isFresh) {
        [_reservedCourses removeAllObjects];
    }
    
    OCGumboDocument *document = [[OCGumboDocument alloc] initWithHTMLString:request.responseString];
    NSArray *rows = document.Query(@"div.bookrecordlist-container").find(@"div.course-item");
    for (OCGumboNode *row in rows) {
        OCGumboNode *name = row.Query(@"div.clearfix").get(0);
        OCGumboNode *time = row.Query(@"div.clearfix").get(1);
        OCGumboNode *teacher = row.Query(@"div.clearfix").get(2);
        OCGumboNode *address = row.Query(@"div.clearfix").get(3);
//        OCGumboNode *student = row.Query(@"div.clearfix").get(4);
        OCGumboNode *courseIdNode = nil;
        NSString *courseId = nil;
        
        NSArray *buttonsArr = row.Query(@"div.course-buttons").find(@"a");
        if (buttonsArr.count == 1) {
            courseIdNode = [buttonsArr objectAtIndex:0];
        }
        else if (buttonsArr.count == 2) {
            courseIdNode = [buttonsArr objectAtIndex:1];
        }
        else {
            DDLogInfo(@"获取课程id错误");
            continue;
        }
        
        courseId = courseIdNode.attr(@"onclick");
        NSRange beginRange = [courseId rangeOfString:@"("];
        NSRange overRange = [courseId rangeOfString:@")"];
        if (beginRange.location != NSNotFound) {
            courseId = [courseId substringWithRange:NSMakeRange(beginRange.location + 2,
                                                                overRange.location - beginRange.location - 2)];
        
        }
        
        CourseModel *model = [[CourseModel alloc] initWithCourseName:name.text()
                                                                time:time.text()
                                                             teacher:teacher.text()
                                                             address:address.text()
                                                        studentCount:@""
                                                            courseId:courseId];
        [_reservedCourses addObject:model];
        DDLogInfo(@"%@  %@  %@  %@  %@",model.name,model.time,model.teacher,model.address,model.studentCount);
    }
    
    //循环获取已订课程记录
    if (rows.count >= 5 ) {
        _isFresh = NO;
       NSInteger pageIndex = [[request.userInfo objectForKey:@"page"] integerValue];
        pageIndex++;
        [self searchCourses:pageIndex];
        return;
    }
    
    if (_delegate && [_delegate respondsToSelector:@selector(searchCoursesSuccess:)]) {
        [_delegate performSelector:@selector(searchCoursesSuccess:) withObject:_reservedCourses];
    }
}

- (void)courseListSuccess:(ASIHTTPRequest *)request {
    
    OCGumboDocument *document = [[OCGumboDocument alloc] initWithHTMLString:request.responseString];
    NSArray *rows = document.Query(@"tbody.site-content").find(@"tr");
    if (rows.count == 0) {
        DDLogError(@"没有可订课程");
        return;
    }
    
    NSMutableArray *coursesArr = [[NSMutableArray alloc] init];
    for (OCGumboNode *node in rows) {
        NSString *name = [node.Query(@"td").get(0).text() stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n "]];
        NSString *teacher = [node.Query(@"td").get(1).text() stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n "]];
        NSString *address = [node.Query(@"td").get(2).text() stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n "]];
        NSString *time = [node.Query(@"td").get(3).text() stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        time = [time stringByReplacingOccurrencesOfString:@" " withString:@""];
        NSString *reservedNum = [node.Query(@"td").get(4).text() stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n "]];
        NSString *queuedNum = [node.Query(@"td").get(5).text() stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\r\n "]];
        NSString *status = node.Query(@"td").get(6).text();
        
        NSString *courseId = nil;
        NSArray *test = node.Query(@"td").get(6).Query(@"a");
        if (test.count != 0) {
            OCGumboNode *row = [test objectAtIndex:0];
            courseId = row.attr(@"onclick");
        }
        
        //课程类别(主修,SC,ISHOW或其它)
        NSString *courseCategory = node.attr(@"sType");
        
        CourseModel *model = [[CourseModel alloc] init];
        model.name = name;
        model.teacher = teacher;
        model.address = address;
        model.time = time;
        model.resevedNum = reservedNum;
        model.queuedNum = queuedNum;
        model.status = status;
        model.courseId = courseId;
        [model setCourseCategoryWithString:courseCategory];
        
        [coursesArr addObject:model];
    }
    
    if (_delegate && [_delegate respondsToSelector:@selector(courseListSuccess:)]) {
        [_delegate performSelector:@selector(courseListSuccess:) withObject:coursesArr];
    }
}

- (void)reserveCourseSuccess:(ASIHTTPRequest *)request {
    NSData *data = [request.responseString dataUsingEncoding:NSUTF8StringEncoding];
    
    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    if (![jsonObject isKindOfClass:[NSDictionary class]]){
        [SVProgressHUD dismiss];
        DDLogInfo(@"解析失败!");
        return;
    }
    
    if (_reserveDelegate && [_reserveDelegate respondsToSelector:@selector(reserveCourseSuccess:reserveCourseResult:)]) {
        //订课成功后
        [_reserveDelegate performSelector:@selector(reserveCourseSuccess:reserveCourseResult:)
                               withObject:[request.userInfo objectForKey:@"course"]
                               withObject:[jsonObject objectForKey:@"status"]];
    }
    
}

/**
 * @ get studentId!
 */

- (void)getStudentId:(ASIHTTPRequest *)request {
    NSString *string = request.responseString;
    NSError *error = nil;
    HTMLParser *parser = [[HTMLParser alloc] initWithString:string error:&error];
    if (error) {
        DDLogInfo(@"error ocurred!");
        return;
    }
    
    HTMLNode *bodyNode = [parser body];
    NSArray *inputNodes = [bodyNode children];
    NSString *studentId = nil;
    
    for (HTMLNode *node in inputNodes) {
        if ([node.className isEqualToString:@"bodyer"]) {
            NSRange range = [node.allContents rangeOfString:@"/Site/LayoutProgress\", { studentId: "];
            NSUInteger location = range.location + range.length + 1;
            NSString *substring = [node.allContents substringFromIndex:location];
            NSArray *array = [substring componentsSeparatedByString:@" "];
            studentId = [array objectAtIndex:0];
            studentId = [studentId substringToIndex:studentId.length - 1];
            break;
        }
    }
    
    [self userLevel:studentId];
}

/**
 * @ parse User Level
 */

- (void)parseUserLevel:(ASIHTTPRequest *)request {
    OCGumboDocument *document = [[OCGumboDocument alloc] initWithHTMLString:request.responseString];
    NSArray *rows = document.Query(@"div.progress-container").find(@"a");

    OCGumboNode *node = [rows objectAtIndex:0];
    
    NSString *level = node.attr(@"href");
    NSRange range = [level rangeOfString:@"productLevelId="];
    NSUInteger location = range.location + range.length;
    level = [level substringFromIndex:location];
    
    if (_delegate && [_delegate respondsToSelector:@selector(getUserLevel:)]) {
        [_delegate performSelector:@selector(getUserLevel:) withObject:level];
    }
}

- (void)cancelHandle:(ASIHTTPRequest *)request {
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:request.responseData options:NSJSONReadingMutableContainers error:nil];
    
    id result = [dic objectForKey:@"status"];
    if (_cancelCourseDelegate && [_cancelCourseDelegate respondsToSelector:@selector(cancelCourseResult:)]) {
        [_cancelCourseDelegate performSelector:@selector(cancelCourseResult:) withObject:result];
    }
}

- (void)standByOrCancelQueueBack:(ASIHTTPRequest *)request {
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:request.responseData options:NSJSONReadingMutableContainers error:nil];
    DDLogInfo(@"dic is %@", dic);
    id result = [dic objectForKey:@"status"];
    
    if (request.tag == REQUEST_STANDBY) {
        if (_reserveDelegate && [_reserveDelegate respondsToSelector:@selector(standByCourseSuccess:queueResult:)]) {
            [_reserveDelegate performSelector:@selector(standByCourseSuccess:queueResult:) withObject:[request.userInfo objectForKey:@"course"] withObject:result];
        }
    }
    else {
        if (_reserveDelegate && [_reserveDelegate respondsToSelector:@selector(cancelStandBySuccess:cancelQueueResult:)]) {
            [_reserveDelegate performSelector:@selector(cancelStandBySuccess:cancelQueueResult:) withObject:[request.userInfo objectForKey:@"course"] withObject:result];
        }
    }
}

@end
